----------------------------------------------------------------------------
--BossWatch
--A lightweight addon to analyze bossencounters fast and 'on the fly'
--
--Author: Ayeshaa --Taerar(eu)
--
----------------------------------------------------------------------------
local Bosswatch = LibStub("AceAddon-3.0"):NewAddon("Bosswatch", "AceConsole-3.0","AceEvent-3.0")
local AceGUI = LibStub("AceGUI-3.0")

------- Useful Local Variables
--
local logging = nil
local starttime = nil
local logname = nil
local logfilter = {}
local currentlog = nil
local insert = table.insert
local fmt = string.format
local advfilterselect = AceGUI:Create("ScrollFrame")
local filterselect = AceGUI:Create("ScrollFrame")
local sourceselect = AceGUI:Create("ScrollFrame")
local fightselectgroup = AceGUI:Create("ScrollFrame")
local logframe = AceGUI:Create("ScrollFrame")
local fightlabel = {}
local sourcelabel = {}
local filterlabel = {}
local advfilterlabel = {}
local fightselected = nil
local sourceselected = nil
local filterselected = nil
local advfilterselected = nil
local frame = nil
local autoenable = nil
---------

---------Databroker Stuff
local ldb = LibStub:GetLibrary("LibDataBroker-1.1"):NewDataObject("Bosswatch", {
	type = "data source",
	text = "|cff696969Idle|r",
	icon = "Interface\\AddOns\\BossWatch\\Icon_off",
	OnTooltipShow = function(tt)
		if logging then
			tt:AddLine(logname, 1, 1, 1, 1)
		else
			tt:AddLine("|cff696969Idle|r", 1, 1, 1, 1)
		end
		tt:AddLine(" ")
		tt:AddLine("|cffeda55fClick|r to start or stop logging. |cffeda55fShift-Click|r to enable autologging. |cffeda55fAlt-Middle Click|r to clear all stored data. |cffeda55fRight Click|r to open window" , 0.2, 1, 0.2, 1)
	end,
	OnClick = function(self, button)
		if button == "LeftButton" then
			if IsShiftKeyDown() then Bosswatch:Autoenable()
			elseif not logging then
				Bosswatch:Start()
			else
				Bosswatch:Stop()
			end
		elseif button == "RightButton" then
			 Bosswatch:OpenFrame()
		elseif button == "MiddleButton" and IsAltKeyDown() then
			Bosswatch:Clearlog()
		end
	end,
})

local myicon = LibStub("LibDBIcon-1.0")
------------


function Bosswatch:OnInitialize()
	Bosswatch:Print("Loaded")
	Bosswatch:RegisterChatCommand("bowa", "Command")
	myicon:Register("Bosswatch!", ldb, false)
	if type(BosswatchDB) ~= "table" then BosswatchDB = {} end
	
	-- Do Cool Stuff
	
	-- Combatlog Filter
	logfilter["SPELL_CAST_START"] = true
	logfilter["SPELL_CAST_SUCCESS"] = true
	logfilter["SPELL_DAMAGE"] = true
	logfilter["SPELL_AURA_APPLIED"] = true
	logfilter["SPELL_AURA_APPLIED_DOSE"] = true
	logfilter["SPELL_SUMMON"] = true
end

function Bosswatch:Start()
	if logging then Bosswatch:Print("Already Logging")
	else
		self:RegisterEvent("COMBAT_LOG_EVENT_UNFILTERED")
		self:RegisterEvent("CHAT_MSG_MONSTER_YELL")
		self:RegisterEvent("CHAT_MSG_RAID_BOSS_EMOTE")
		self:RegisterEvent("CHAT_MSG_RAID_BOSS_WHISPER")
		ldb.text = "|cff00FF00Logging|r"
		ldb.icon = "Interface\\AddOns\\BossWatch\\Icon_on"
		logging = true
		starttime = GetTime()
		logname = date("%H:%M:%S")
		BosswatchDB[logname] = {}
		currentlog = BosswatchDB[logname]
		Bosswatch:Print("Logging...")
	end	
end

function Bosswatch:Stop()
	if logging then
		self:UnregisterEvent("COMBAT_LOG_EVENT_UNFILTERED")
		self:UnregisterEvent("CHAT_MSG_MONSTER_YELL")
		self:UnregisterEvent("CHAT_MSG_RAID_BOSS_EMOTE")
		self:UnregisterEvent("CHAT_MSG_RAID_BOSS_WHISPER")
		if autoenable then ldb.text = "|cff006900StandBy..|r" 
		else ldb.text = "|cff696969Idle|r" end
		ldb.icon = "Interface\\AddOns\\BossWatch\\Icon_off"
		logging = false
		Bosswatch:Print("...Stopped Logging")
	end
end

function Bosswatch:Command(args)	
	if args == "start" then self:Start() 
	elseif args == "stop" then self:Stop() 
	elseif args == "show" then self:OpenFrame()
	elseif args == "clear" then self:Clearlog()
	elseif args == "auto" then self:Autoenable()
	else
		self:Print("Usable Commands:")
		self:Print("-start | starts logging")
		self:Print("-stop  | stop logging")
		self:Print("-show  | shows frame")
		self:Print("-clear | clears stored sessions")
		self:Print("-auto  | autolog on combat")
	end
end
function Bosswatch:Clearlog()
	BosswatchDB = {}
	self:Print("Cleared Everything")
end

function Bosswatch:Autoenable()
	if autoenable then
		self:UnregisterEvent("PLAYER_REGEN_DISABLED")
		self:UnregisterEvent("PLAYER_REGEN_ENABLED")
		autoenable = false
		ldb.text = "|cff696969Idle|r"
	else
		self:RegisterEvent("PLAYER_REGEN_DISABLED")
		self:RegisterEvent("PLAYER_REGEN_ENABLED")
		autoenable = true
		ldb.text = "|cff006900StandBy..|r"
		self:Print("Standby...")
	end
end

function Bosswatch:PLAYER_REGEN_DISABLED()
	self:Start()
end

function Bosswatch:PLAYER_REGEN_ENABLED()
	self:Stop()
end

function Bosswatch:CHAT_MSG_MONSTER_YELL( _, text, source)
	self:Insertevent( "yell", source, nil, nil, nil, text)
end

function Bosswatch:CHAT_MSG_RAID_BOSS_EMOTE( _,text, source)
	self:Insertevent( "emote", source, nil, nil, nil, text)
end

function Bosswatch:CHAT_MSG_RAID_BOSS_WHISPER(_,text, source)
	self:Insertevent( "whisper", source, nil, nil, nil, text)
end

function Bosswatch:COMBAT_LOG_EVENT_UNFILTERED(_, _, event, _,_, source, sflag, _,_, player, pflag,_, spellId, spellName)
	if bit.band(sflag, COMBATLOG_OBJECT_AFFILIATION_MASK) <	8 then
	elseif sflag then
		if logfilter[event] then
			self:Insertevent(event, source, player, spellId, spellName, nil)
		end
	end		
end

function Bosswatch:Insertevent(event, source, player, spellId, spellName, text)
	local currenttime = GetTime()
	local timediff = currenttime - starttime
	local timediffstr = fmt("%.1f", timediff)
	
	if not player then player = " " end
	if not source then source = "Enviroment" end
	
	if type(currentlog[source]) ~= "table" then 
		currentlog[source] = {}
		currentlog[source]["total"] = {}
		currentlog[source]["spells"] = {}
		currentlog[source]["yells"] = {}
		currentlog[source]["emotes"] = {}
		currentlog[source]["whispers"] = {}
	end
	
	if event == "yell" then
		insert(currentlog[source]["yells"], "("..timediffstr..") "..source..": "..text)			--thats enough logging for yells emotes & whispers
		
	elseif event == "emote" then
		insert(currentlog[source]["emotes"], "("..timediffstr..") "..source..": "..text)
		
	elseif event == "whisper" then
		insert(currentlog[source]["whispers"], "("..timediffstr..") "..source..": "..text)
	
	else
		if type(currentlog[source]["spells"][spellId]) ~= "table" then
			currentlog[source]["spells"][spellId] = {}
		end
		if type(currentlog[source]["spells"][spellId][timediffstr]) ~= "table" then
			currentlog[source]["spells"][spellId][timediffstr] = {}
		end 
		if type(currentlog[source]["spells"][spellId][timediffstr][event]) ~= "table" then
			currentlog[source]["spells"][spellId][timediffstr][event] = {}
		end
		
		
		insert(currentlog[source]["total"],  "("..timediffstr..")"..source..":"..player.." - "..spellName.."("..spellId..")".." - ("..event..")")
		insert(currentlog[source]["spells"][spellId][timediffstr][event], player)
	end
	--insert(currentlog[event], "("..timediff..")"..source..":"..player.." - "..spellName.."("..spellId..")")
end




local function Showlog(fight, source, filter, advfilter)
	local loglabel = {}
	if filter == "total" then
		for i in pairs(BosswatchDB[fight][source][filter]) do
			loglabel[i] = AceGUI:Create("InteractiveLabel")
			loglabel[i]:SetText(BosswatchDB[fight][source][filter][i])
			loglabel[i]:SetRelativeWidth(1)
			loglabel[i]:SetHeight(15)
			loglabel[i]:SetHighlight( 0.2, 0.2, 0, 0.5)
			loglabel[i]:SetCallback("OnClick", function(widget) ChatEdit_InsertLink(BosswatchDB[fight][source][filter][i]) end)
			logframe:AddChild(loglabel[i])
		end
	elseif filter == "spells" then
		-- sorts table according to timedifference
		local sortme = {}
		for i in pairs (BosswatchDB[fight][source][filter][advfilter]) do insert(sortme, tonumber(i)) end		
		table.sort(sortme)			
		for i,n in ipairs(sortme) do
			local targets = ""
			local j = 0
			local k = ""..n..""
			if type(BosswatchDB[fight][source][filter][advfilter][k]) == "table" then
				for p in pairs(BosswatchDB[fight][source][filter][advfilter][k]) do
				
					if type(BosswatchDB[fight][source][filter][advfilter][k][p]) == "table" then
						
						for v in pairs(BosswatchDB[fight][source][filter][advfilter][k][p]) do  
							if BosswatchDB[fight][source][filter][advfilter][k][p][v] ~= " " then
								if j > 0 then targets = targets..", " end
								targets = targets..BosswatchDB[fight][source][filter][advfilter][k][p][v]
								j= j+1
							end
						end
						
					end
					
					local logentry = "("..n..") "..source..":("..targets..") - "..GetSpellInfo(advfilter).." - "..p
					loglabel[n] = AceGUI:Create("InteractiveLabel")
					loglabel[n]:SetText(logentry)
					loglabel[n]:SetRelativeWidth(1)
					loglabel[n]:SetHeight(15)
					loglabel[n]:SetHighlight( 0.2, 0.2, 0, 0.5)
					loglabel[n]:SetCallback("OnClick", function(widget) ChatEdit_InsertLink("("..n..") "..source.." - "..GetSpellLink(advfilter).." - "..p.." ("..j.." hits)") end)
					logframe:AddChild(loglabel[n])
				end
			end
		end
	else
		for i in pairs(BosswatchDB[fight][source][filter]) do
			loglabel[i] = AceGUI:Create("InteractiveLabel")
			loglabel[i]:SetText(BosswatchDB[fight][source][filter][i])
			loglabel[i]:SetRelativeWidth(1)
			loglabel[i]:SetHeight(15)
			loglabel[i]:SetHighlight( 0.2, 0.2, 0, 0.5)
			loglabel[i]:SetCallback("OnClick", function(widget) ChatEdit_InsertLink(BosswatchDB[fight][source][filter][i]) end)
			logframe:AddChild(loglabel[i])
		end			
	end
	frame:DoLayout()
end

local function Advfilter(fight, source, filter)
	if filter == "total" or filter == "yells" or filter == "emotes" or filter == "whispers"  then
		Showlog(fight, source, filter, nil)
	elseif filter == "spells" then	
		for i in pairs(BosswatchDB[fight][source][filter]) do
			advfilterlabel[i] = AceGUI:Create("InteractiveLabel")
			advfilterlabel[i]:SetText(GetSpellInfo(i))
			advfilterlabel[i]:SetRelativeWidth(1)
			advfilterlabel[i]:SetHeight(15)
			advfilterlabel[i]:SetHighlight( 0.2, 0.2, 0, 0.5)
			advfilterlabel[i]:SetCallback("OnClick", function(widget) 
				if IsShiftKeyDown() then ChatEdit_InsertLink(GetSpellLink(i).."("..i..")") 
				else 
					logframe:ReleaseChildren()
					Showlog(fight, source, filter, i)
					widget:SetColor(1,0,0,1)
					if advfilterselected and advfilterselected ~= i then advfilterlabel[advfilterselected]:SetColor(1,1,1,1) end
					advfilterselected = i
				end
			end)
			advfilterlabel[i]:SetCallback("OnEnter", function(widget)
				GameTooltip:SetOwner(UIParent, "ANCHOR_CURSOR")
				--GameTooltip:SetPoint("
				GameTooltip:SetHyperlink(GetSpellLink(i))
				GameTooltip:AddLine("Shift + Left Click to link in chat", 0,1,0)
				GameTooltip:Show()
			end)
			advfilterlabel[i]:SetCallback("OnLeave", function(widget) GameTooltip:Hide() end)
			advfilterlabel[i]:SetPoint("TOP")
			advfilterselect:AddChild(advfilterlabel[i])
		end
	end
	frame:DoLayout()
end
			
			

local function SourceSelect(fight, source)
	filterselect:ReleaseChildren()
	for i in pairs(BosswatchDB[fight][source]) do
		filterlabel[i] = AceGUI:Create("InteractiveLabel")
		filterlabel[i]:SetText(i)
		filterlabel[i]:SetRelativeWidth(1)
		filterlabel[i]:SetHeight(15)
		filterlabel[i]:SetHighlight( 0.2, 0.2, 0, 0.5)
		filterlabel[i]:SetCallback("OnClick", function(widget)
			logframe:ReleaseChildren()
			advfilterselect:ReleaseChildren()
			Advfilter(fight, source, i)
			widget:SetColor(1,0,0,1)
			if filterselected and filterselected ~= i then filterlabel[filterselected]:SetColor(1,1,1,1) end
			filterselected = i
		end)
		filterlabel[i]:SetPoint("TOP")
		filterselect:AddChild(filterlabel[i])
	end
	frame:DoLayout()
end

local function FightSelected(fight)
	sourceselect:ReleaseChildren()
	for k in pairs(BosswatchDB[fight]) do
	
		sourcelabel[k] = AceGUI:Create("InteractiveLabel")
		sourcelabel[k]:SetText(k)
		sourcelabel[k]:SetRelativeWidth(1)
		sourcelabel[k]:SetHeight(15)
		sourcelabel[k]:SetHighlight( 0.2, 0.2, 0, 0.5)
		sourcelabel[k]:SetCallback("OnClick", function(widget) 
			filterselect:ReleaseChildren()
			logframe:ReleaseChildren()
			advfilterselect:ReleaseChildren()
			SourceSelect(fight, k)
			widget:SetColor(1,0,0,1)
			if sourceselected and sourceselected ~= k then sourcelabel[sourceselected]:SetColor(1,1,1,1) end
			sourceselected = k
		end)
		sourcelabel[k]:SetPoint("TOP")
		sourcelabel[k].fight = fight
		sourceselect:AddChild(sourcelabel[k])
		
	end
	frame:DoLayout()
end




			
	


function Bosswatch:OpenFrame()

	if frame then 
		
		frame:Show()
		fightselectgroup:ReleaseChildren()
		for i in pairs(BosswatchDB) do
	
			fightlabel[i] = AceGUI:Create("InteractiveLabel")
			fightselectgroup:AddChild(fightlabel[i])
			fightlabel[i]:SetText(i)
			fightlabel[i]:SetRelativeWidth(1)
			fightlabel[i]:SetHeight(15)
			fightlabel[i]:SetHighlight( 0.4, 0.4, 0, 0.5)
			fightlabel[i]:SetCallback("OnClick", function(widget)
				filterselect:ReleaseChildren()
				logframe:ReleaseChildren()
				sourceselect:ReleaseChildren()
				advfilterselect:ReleaseChildren()
				FightSelected(widget.fight)
				widget:SetColor(1,0,0,1)
				if fightselected and fightselected ~= i then fightlabel[fightselected]:SetColor(1,1,1,1) end
				fightselected = i
			end)
			fightlabel[i]:SetPoint("TOP")
			fightlabel[i].fight = i
		end
	else
		frame = AceGUI:Create("Window")
		frame:SetTitle("Bosswatch")
		frame:ReleaseChildren()
		frame:SetLayout("Flow")
		frame:SetCallback("OnClose", function(widget) 
		frame:Hide()
	end)
	frame:SetWidth(600)
	frame:SetHeight(400)
	
	fightselectgroup:SetRelativeWidth(0.25)
	fightselectgroup:SetFullHeight(true)
	fightselectgroup:ClearAllPoints()
	fightselectgroup:ReleaseChildren()
	fightselectgroup:SetPoint("TOPRIGHT")
	fightselectgroup:SetLayout("List")
	
	sourceselect:SetRelativeWidth(0.25)
	sourceselect:SetFullHeight(true)
	sourceselect:ClearAllPoints()
	sourceselect:ReleaseChildren()
	sourceselect:SetPoint("TOPLEFT")
	sourceselect:SetLayout("List")
	
	fightselectgroup:SetPoint("TOPRIGHT")
	
	filterselect:SetRelativeWidth(0.25)
	filterselect:SetFullHeight(true)
	filterselect:ClearAllPoints()
	filterselect:ReleaseChildren()
	filterselect:SetPoint("TOP")
	filterselect:SetLayout("List")
	
	advfilterselect:SetRelativeWidth(0.25)
	advfilterselect:SetFullHeight(true)
	advfilterselect:ClearAllPoints()
	advfilterselect:ReleaseChildren()
	advfilterselect:SetPoint("TOP")
	advfilterselect:SetLayout("List")
	
	
	local logborderframe = AceGUI:Create("SimpleGroup")
	local selectorframe = AceGUI:Create("SimpleGroup")
	local outerselectorframe = AceGUI:Create("SimpleGroup")
	local filterselectframe = AceGUI:Create("SimpleGroup")
	local fightselectgroupframe = AceGUI:Create("SimpleGroup")
	local sourceselectframe = AceGUI:Create("SimpleGroup")
	local advfilterselectframe = AceGUI:Create("SimpleGroup")
	
	outerselectorframe:SetFullWidth(true)
	outerselectorframe:SetHeight(150)
	outerselectorframe:ClearAllPoints()
	outerselectorframe:ReleaseChildren()
	outerselectorframe:SetPoint("TOP")
	outerselectorframe:SetLayout("Fill")

	advfilterselectframe:SetRelativeWidth(0.25)
	advfilterselectframe:SetFullHeight(true)
	advfilterselectframe:ClearAllPoints()
	advfilterselectframe:ReleaseChildren()
	advfilterselectframe:SetPoint("TOP")
	advfilterselectframe:SetLayout("Fill")
	
	sourceselectframe:SetRelativeWidth(0.25)
	sourceselectframe:SetFullHeight(true)
	sourceselectframe:ClearAllPoints()
	sourceselectframe:ReleaseChildren()
	sourceselectframe:SetPoint("TOP")
	sourceselectframe:SetLayout("Fill")
	
	filterselectframe:SetRelativeWidth(0.25)
	filterselectframe:SetFullHeight(true)
	filterselectframe:ClearAllPoints()
	filterselectframe:ReleaseChildren()
	filterselectframe:SetPoint("TOP")
	filterselectframe:SetLayout("Fill")
	
	fightselectgroupframe:SetRelativeWidth(0.25)
	fightselectgroupframe:SetFullHeight(true)
	fightselectgroupframe:ClearAllPoints()
	fightselectgroupframe:ReleaseChildren()
	fightselectgroupframe:SetPoint("TOP")
	fightselectgroupframe:SetLayout("Fill")
	
	
	selectorframe:SetFullWidth(true)
	selectorframe:SetHeight(200)
	selectorframe:ClearAllPoints()
	selectorframe:ReleaseChildren()
	selectorframe:SetPoint("TOP")
	selectorframe:SetLayout("Flow")	

	
	logborderframe:SetFullWidth(true)
	logborderframe:SetHeight(200)
	logborderframe:ClearAllPoints()
	logborderframe:ReleaseChildren()
	logborderframe:SetPoint("BOTTOMLEFT")
	logborderframe:SetLayout("Fill")	
	
	logframe:SetFullWidth(true)
	logframe:SetHeight(200)
	logframe:ClearAllPoints()
	logframe:ReleaseChildren()
	logframe:SetPoint("BOTTOMLEFT")
	logframe:SetLayout("List")
	
	fightselectgroupframe:AddChild(fightselectgroup)
	filterselectframe:AddChild(filterselect)
	sourceselectframe:AddChild(sourceselect)
	advfilterselectframe:AddChild(advfilterselect)
	logborderframe:AddChild(logframe)
	selectorframe:AddChild(fightselectgroupframe)
	selectorframe:AddChild(sourceselectframe)
	selectorframe:AddChild(filterselectframe)
	selectorframe:AddChild(advfilterselectframe)
	outerselectorframe:AddChild(selectorframe)
	frame:AddChild(outerselectorframe)
	frame:AddChild(logborderframe)
	
	
	
	

	for i in pairs(BosswatchDB) do
	
		fightlabel[i] = AceGUI:Create("InteractiveLabel")
		fightselectgroup:AddChild(fightlabel[i])
		fightlabel[i]:SetText(i)
		fightlabel[i]:SetRelativeWidth(1)
		fightlabel[i]:SetHeight(15)
		fightlabel[i]:SetHighlight( 0.4, 0.4, 0, 0.5)
		fightlabel[i]:SetCallback("OnClick", function(widget)
			filterselect:ReleaseChildren()
			logframe:ReleaseChildren()
			sourceselect:ReleaseChildren()
			advfilterselect:ReleaseChildren()
			FightSelected(widget.fight)
			widget:SetColor(1,0,0,1)
			if fightselected and fightselected ~= i then fightlabel[fightselected]:SetColor(1,1,1,1) end
			fightselected = i
		end)
		fightlabel[i]:SetPoint("TOP")
		fightlabel[i].fight = i
		
	end
	
	end
	frame:DoLayout()
end


function Bosswatch:OnEnable()
	
	-- Do Cooler Stuff
end

function Bosswatch:OnDisable()

	-- Clean
end





